﻿#ifndef AudioFilter_H
#define AudioFilter_H

#include <map>
#include <mutex>
#include <cstdio>
#include <cstdint>
#include <string>
#include <memory>

extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavutil/opt.h>

#define printf(format, ...) \
    (printf)("\033[36m[%s][%s:%d]#zmo#" format "\033[0m\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
}

class AudioFilter
{
public:
    AudioFilter();
    virtual ~AudioFilter();

    int addAudioInput(uint32_t index, uint32_t samplerate, uint32_t channels, uint32_t samplingAccuracy, AVSampleFormat format);
    int addAudioOutput(const uint32_t samplerate, const uint32_t channels,
                       const uint32_t samplingAccuracy, const AVSampleFormat format);

    int init(const char *duration = "longest");
    int exit();

    int addFrame(uint32_t index, uint8_t *inBuf, uint32_t size);
    int getFrame(uint8_t *outBuf, uint32_t maxOutBufSize);
    void setCustomFilter(const std::string &p_strCustomFilterDescr);
    const std::string &getCustomFilter() const;

private:
    struct AudioInfo
    {
        AudioInfo()
        {
            filterCtx = nullptr;
        }

        uint32_t samplerate;
        uint32_t channels;
        uint32_t samplingAccuracy;
        AVSampleFormat format;
        std::string name;

        AVFilterContext *filterCtx;
    };

    bool m_initialized = false;
    std::mutex m_mutex;
    std::string m_strCustomFilterDescr;
    std::map<uint32_t, AudioInfo> m_mapAudioInputInfo;
    std::shared_ptr<AudioInfo> m_pAudioOutputInfo;
    std::shared_ptr<AudioInfo> m_pAudioMixInfo;
    std::shared_ptr<AudioInfo> m_pAudioSinkInfo;

    AVFilterGraph *m_objFilterGraph = nullptr;
};
#endif // AudioFilter_H
